// 给定一个字符串 (s) 和一个字符模式 (p) ，实现一个支持 '?' 和 '*' 的通配符匹配。

// '?' 可以匹配任何单个字符。
// '*' 可以匹配任意字符串（包括空字符串）。
// 两个字符串完全匹配才算匹配成功。

// 说明:

// s 可能为空，且只包含从 a-z 的小写字母。
// p 可能为空，且只包含从 a-z 的小写字母，以及字符 ? 和 *。
// 示例 1:

// 输入:
// s = "aa"
// p = "a"
// 输出: false
// 解释: "a" 无法匹配 "aa" 整个字符串。
// 示例 2:

// 输入:
// s = "aa"
// p = "*"
// 输出: true
// 解释: '*' 可以匹配任意字符串。
// 示例 3:

// 输入:
// s = "cb"
// p = "?a"
// 输出: false
// 解释: '?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。
// 示例 4:

// 输入:
// s = "adceb"
// p = "*a*b"
// 输出: true
// 解释: 第一个 '*' 可以匹配空字符串, 第二个 '*' 可以匹配字符串 "dce".
// 示例 5:

// 输入:
// s = "acdcb"
// p = "a*c?b"
// 输出: false

#include <string>
#include <vector>

using namespace std;


// 动态规划
// dp[i][j] 表示字符串 ss 的前 ii 个字符和模式 pp 的前 jj 个字符是否能匹配
// 时间复杂度：O(MN)
// 空间复杂度：O(MN)
class Solution {
public:
    bool isMatch(string s, string p) {
        int m = s.size();
        int n = p.size();
        vector<vector<bool>> dp(m + 1, vector<bool>(n + 1, false));
        dp[0][0] = true; // s和p均为空时
        for (int i{1}; i <= n; ++i) {
            // 只有当p的前i个字符均为*时，才能匹配空字符
            if (p[i - 1] == '*') dp[0][i] = true;
            else break;
        }
        for (int i{1}; i <= m; ++i) {
            for (int j{1}; j <= n; ++j) {
                if (p[j - 1] == '*') { // 分为使用和不使用这个*
                    dp[i][j] = dp[i][j-1] | dp[i - 1][j];
                } else if (p[j - 1] == '?' || p[j - 1] == s[i - 1]) {
                    dp[i][j] = dp[i - 1][j - 1];
                }
            }
        }
        return dp[m][n];
    }
};

// 贪心
class Solution {
public:
    bool isMatch(string s, string p) {
        int i{0}; // s串中当前遍历到的位置
        int j{0}; // p串中当前遍历到的位置
        int iStar{-1}; // *匹配到s串中的位置
        int jStar{-1}; // *在p串中的位置
        while (i < s.size()) {
            if (s[i] == p[j] || p[j] == '?') {
                ++i;
                ++j;
            } else if (p[j] == '*') {
                iStar = i;
                jStar = j++;
            } else if (iStar >= 0) {
                i = ++iStar;
                j = jStar + 1;
            } else return false;
        }
        while (j < p.size() && p[j] == '*') ++j; 
        return j == p.size();
    }
};

// 贪心算法
// 时间复杂度：O(MlogN)
// 空间复杂度：O(1)
class Solution {
public:
    bool isMatch(string s, string p) {
        auto allStars = [](const string& str, const int& left, const int& right) {
            for (int i{left}; i < right; ++i) {
                if (str[i] != '*') return false;
            }
            return true;
        };
        auto charMatch = [](const char& u, const char& v) {
            return (u == v) || (v == '?');
        };
        // 从后面开始匹配
        while (s.size() && p.size() && p.back() != '*') {
            if (charMatch(s.back(), p.back())) {
                s.pop_back();
                p.pop_back();
            } else return false;
        }
        if (p.empty()) return s.empty();
        int sIndex{0};
        int pIndex{0};
        int sRecord{-1};
        int pRecord{-1};
        while (sIndex < s.size() && pIndex < p.size()) {
            if (p[pIndex] == '*') {
                ++pIndex;
                sRecord = sIndex;
                pRecord = pIndex;
            } else if (charMatch(s[sIndex], p[pIndex])) {
                ++sIndex;
                ++pIndex;
            } else if (sRecord != -1 && sRecord + 1 < s.size()) {
                ++sRecord;
                sIndex = sRecord;
                pIndex = pRecord;
            } else return false;
        }
        return allStars(p, pIndex, p.size()); // p剩下的后面是不是全是*
    }
};
